package ssau.knyazev.mmoi.module;

import java.util.Random;

import ssau.knyazev.core.Complex;
import ssau.knyazev.core.ComplexMath;
import ssau.knyazev.core.image.ComplexImageModel;
import ssau.knyazev.mmoi.ModelSettings;


public class ObserveModule {

	private ObserveModule(){}
	
	public static ComplexImageModel opticH(ComplexImageModel cim){
		Complex[][] arr = cim.getValues();
		for (int i = 0; i < arr.length; i++){
			for (int j = 0; j < arr[0].length; j++){
				double omega1 = -Math.PI/2 + Math.PI*i/arr.length;
				double omega2 = -Math.PI/2 + Math.PI*j/arr[0].length;
				double arg = (omega1*omega1 + omega2*omega2)/(ModelSettings.omega0*ModelSettings.omega0);
				Complex fst = new Complex((float)Math.sqrt(arg), 0);
				Complex snd = ComplexMath.sqrt(new Complex((float)(1-arg), 0));
				snd = snd.multyBy(-1).incBy(1);
				fst = fst.multy(snd);
				arr[i][j] = ComplexMath.acos(fst);
				arr[i][j] = arr[i][j].multyBy(2/Math.PI);
			}
		}
		mirror(arr);
		return cim;
	}


	
	public static ComplexImageModel videoWorkH0(ComplexImageModel cim){
		Complex[][] arr = cim.getValues();
		for (int i = 0; i < arr.length; i++){
			for (int j = 0; j < arr[0].length; j++){
				double omega1 = -Math.PI/2 + Math.PI*i/arr.length;
				double omega2 = -Math.PI/2 + Math.PI*j/arr[0].length;
				double fst = omega1*ModelSettings.L1/2+0.00000000000000001;
				double snd = omega2*ModelSettings.L2/2+0.00000000000000001;
				fst = Math.sin(fst)/fst;
				snd = Math.sin(snd)/snd;
				arr[i][j] = new Complex((float)(fst*snd), 0);
			}
		}
		mirror(arr);
		return cim;
	}
	

	
	public static ComplexImageModel videoWorkHk(ComplexImageModel cim, int k){
		Complex[][] arr = cim.getValues();
		for (int i = 0; i < arr.length; i++){
			for (int j = 0; j < arr[0].length; j++){
				double omega1 = 2*Math.PI*i/arr.length;
				double fst = Math.sin(ModelSettings.S*omega1*k/2);
				double snd = k*Math.sin(ModelSettings.S*omega1/2)+0.0000000000000000001;
				arr[i][j] = new Complex((float)(fst/snd), 0);
			}
		}
		mirror(arr);
		return cim;
	}
	

	
	public static ComplexImageModel videoWorkHsm(ComplexImageModel cim){
		Complex[][] arr = cim.getValues();
		for (int i = 0; i < arr.length; i++){
			for (int j = 0; j < arr[0].length; j++){
				double omega1 = -Math.PI/2 + Math.PI*j/arr.length;
				double omega2 = -Math.PI/2 + Math.PI*i/arr[0].length;
				double fst = omega1*ModelSettings.V1 + omega2*ModelSettings.V2;
				fst = fst*ModelSettings.tetta/2 + 0.0000000000000000000001;
				arr[i][j] = new Complex((float)(Math.sin(fst)/fst), 0);
			}
		}
		mirror(arr);
		return cim;
	}
		
	public static ComplexImageModel videoWorkHsd(ComplexImageModel cim){
		Complex[][] arr = cim.getValues();
		for (int i = 0; i < arr.length; i++){
			for (int j = 0; j < arr[0].length; j++){
				double omega1 = -Math.PI/2 + Math.PI*j/arr.length;
				double omega2 = -Math.PI/2 + Math.PI*i/arr[0].length;
				double fst = omega1*ModelSettings.V1 + omega2*ModelSettings.V2;
				fst = fst*ModelSettings.tetta/2;
				arr[i][j] = Complex.exp(fst);
			}
		}
		mirror(arr);
		return cim;
	}
	
	public static ComplexImageModel generateNoise(ComplexImageModel cim, double SKO, boolean mult){
		Complex[][] arr = new Complex[cim.getValues().length][cim.getValues()[0].length];
		Random rnd = new Random();
		for (int i = 0; i < arr.length; i++){
			for (int j = 0; j < arr[0].length; j++){
				arr[i][j] = (mult) ? new Complex((float)(1 + SKO * rnd.nextGaussian()), 0) : new Complex((float)(SKO * rnd.nextGaussian()), 0);
			}
		}
		return new ComplexImageModel(arr);
	}
	
	private static void mirror(Complex[][] arr){
		Complex temp = null;
		for (int i = 0; i < arr.length/2; i++){
			for (int j = 0; j < arr[0].length/2; j++){
				temp = arr[i][j];
				arr[i][j] = arr[arr.length/2 + i][arr[0].length/2 + j];
				arr[arr.length/2 + i][arr[0].length/2 + j] = temp;
			}
		}
		for (int i = 0; i < arr.length/2; i++){
			for (int j = arr[0].length/2; j < arr[0].length; j++){
				temp = arr[i][j];
				arr[i][j] = arr[arr.length/2 + i][j - arr[0].length/2];
				arr[arr.length/2 + i][j - arr[0].length/2] = temp;
			}
		}
		
	}
	
}
